/**
 * Copyright © 2011 Creativor Studio.
 * About license information, please see LICENSE.txt.
 */
package org.creativor.rayson.client;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.atomic.AtomicBoolean;
import org.creativor.rayson.api.AsyncRpcProtocol;
import org.creativor.rayson.api.RpcProtocol;
import org.creativor.rayson.api.TransferArgument;
import org.creativor.rayson.api.TransferSocket;
import org.creativor.rayson.exception.IllegalServiceException;
import org.creativor.rayson.exception.NetWorkException;
import org.creativor.rayson.exception.ServiceNotFoundException;
import org.creativor.rayson.exception.UnsupportedVersionException;
import org.creativor.rayson.protocol.ServerProtocol;

// TODO: Auto-generated Javadoc
/**
 * Rayson is a communication module for cloud computing. This class is the
 * entrance of the Rayson module to it's client.
 * 
 * @author Nick Zhang
 */
public final class Rayson
{
	private Rayson()
	{
		
	}
	
	private static Client CLIENT = new Client();
	private static AtomicBoolean clientInited = new AtomicBoolean(false);
	
	/**
	 * Creates the proxy.
	 * 
	 * @param <T>
	 *            the generic type
	 * @param serviceName
	 *            the service name
	 * @param proxyInterface
	 *            the proxy interface
	 * @param serverAddress
	 *            the server address
	 * @return the t
	 * @throws IllegalServiceException
	 *             the illegal service exception
	 */
	public static <T extends RpcProtocol> T createProxy(String serviceName,
			Class<T> proxyInterface, InetSocketAddress serverAddress)
			throws IllegalServiceException
	{
		tryInit();
		return CLIENT.createRpcProxy(serviceName, proxyInterface, serverAddress);
	}
	
	/**
	 * Creates the async proxy.
	 * 
	 * @param <T>
	 *            the generic type
	 * @param serviceName
	 *            the service name
	 * @param proxyInterface
	 *            the proxy interface
	 * @param serverAddress
	 *            the server address
	 * @return the t
	 * @throws IllegalServiceException
	 *             the illegal service exception
	 */
	public static <T extends AsyncRpcProtocol> T createAsyncProxy(String serviceName,
			Class<T> proxyInterface, InetSocketAddress serverAddress)
			throws IllegalServiceException
	{
		tryInit();
		return CLIENT.createAsyncProxy(serviceName, proxyInterface, serverAddress);
	}
	
	/**
	 * Open transfer socket.
	 * 
	 * @param serverAddress
	 *            the server address
	 * @param argument
	 *            the argument
	 * @return the transfer socket
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 * @throws ServiceNotFoundException
	 *             the service not found exception
	 * @throws IllegalServiceException
	 *             the illegal service exception
	 * @throws UnsupportedVersionException
	 *             the unsupported version exception
	 */
	public static TransferSocket openTransferSocket(SocketAddress serverAddress,
			TransferArgument argument) throws IOException, ServiceNotFoundException,
			IllegalServiceException, UnsupportedVersionException
	{
		return CLIENT.openTransferSocket(serverAddress, argument);
	}
	
	/**
	 * Gets the server proxy.
	 * 
	 * @param serverAddress
	 *            the server address
	 * @return the server proxy
	 */
	public static ServerProtocol getServerProxy(InetSocketAddress serverAddress)
	{
		tryInit();
		
		return CLIENT.getServerProxy(serverAddress);
	}
	
	/**
	 * Ping.
	 * 
	 * @param serverAddress
	 *            the server address
	 * @throws NetWorkException
	 *             the net work exception
	 */
	public static void ping(SocketAddress serverAddress) throws NetWorkException
	{
		CLIENT.ping(serverAddress);
	}
	
	/**
	 * Gets the client version.
	 * 
	 * @return the client version
	 */
	public static byte getClientVersion()
	{
		return Client.getVersion();
	}
	
	private static void tryInit()
	{
		if (clientInited.compareAndSet(false, true)) CLIENT.start();
	}
}
